//工具函数
/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string | null}
 */
export function parseTime(time, cFormat) {
  if (arguments.length === 0 || !time) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (typeof time === 'string') {
      if (/^[0-9]+$/.test(time)) {
        // support "1548221490638"
        time = parseInt(time)
      } else {
        // support safari
        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
        time = time.replace(new RegExp(/-/gm), '/')
      }
    }

    if (typeof time === 'number' && time.toString().length === 10) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
    const value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    return value.toString().padStart(2, '0')
  })
  return time_str
}

/**
 * @desc 时间格式化
 * @param {string|date} time 接受字符串和Date类型
 * @param {string} option 格式{y}
 */
export function formatTime(time, option) {
  if (typeof time === 'object') {
    time = +time
  }
  const d = new Date(time)
  const now = Date.now()
  const diff = (now - d) / 1000

  if (diff < 30) {
    return '刚刚'
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + '分钟前'
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前'
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
  } else if (diff < 3600 * 24 * 3) {
    return '两天前'
  } else if (diff < 3600 * 24 * 4) {
    return '三天前'
  }
  if (option) {
    return parseTime(time, option)
  } else {
    if (d.getFullYear() == new Date().getFullYear()) {
      return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
    } else {
      return `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日`
    }
  }
}

/**
 * @desc 单位亿万化
 * @param {number|string} num 需要转化的单位
 * @param {number} point 保留几位小时
 * */
export const tranWan = (num, point) => {
  let numStr = num.toString().split('.')[0]
  if (numStr.length < 4) {
    return numStr
  } else if (numStr.length >= 4 && numStr.length <= 8) {
    let decimal = numStr.substring(numStr.length - 4, numStr.length - 4 + point)
    return parseFloat(parseInt(num / 10000) + '.' + decimal) + '万'
  } else if (numStr.length > 8) {
    let decimal = numStr.substring(numStr.length - 8, numStr.length - 8 + point)
    return parseFloat(parseInt(num / 100000000) + '.' + decimal) + '亿'
  }
}

/**
 * @desc 数字千分化
 * @param {number} num 转化的数字
 * @returns {string}
 */
export function toThousands(num) {
  var numStr = (num || 0).toString()
  return numStr.replace(/(\d)(?=(?:\d{4})+$)/g, '$1,')
}

/**
 * @desc 函数防抖
 * @param {fn} func 函数
 * @param {number} wait 延迟执行毫秒数
 * @param {boolean} immediate true 立即执行，false 非立即执行
 */
export function debounce(func, wait, immediate = true) {
  let timeout
  return function () {
    let context = this
    let args = arguments
    if (timeout) clearTimeout(timeout)
    if (immediate) {
      var callNow = !timeout
      timeout = setTimeout(() => {
        timeout = null
      }, wait)
      if (callNow) func.apply(context, args)
    } else {
      timeout = setTimeout(function () {
        func.apply(context, args)
      }, wait)
    }
  }
}

/**
 * @desc 函数节流
 * @param {fn} func 函数
 * @param {number} wait 延迟执行毫秒数
 * @param {number} type 1 时间戳版，2 定时器版
 */
export function throttle(func, wait, type = 1) {
  if (type === 1) {
    var previous = 0
  } else if (type === 2) {
    var timeout
  }
  return function () {
    let context = this
    let args = arguments
    if (type === 1) {
      let now = Date.now()

      if (now - previous > wait) {
        func.apply(context, args)
        previous = now
      }
    } else if (type === 2) {
      if (!timeout) {
        timeout = setTimeout(() => {
          timeout = null
          func.apply(context, args)
        }, wait)
      }
    }
  }
}

/**
 * 开启监听
 * @param {Element} element 元素
 * @param {string} event 函数名
 * @param {fn} handler 处理函数
 */
export function on(element, event, handler) {
  if (element && event && handler) {
    element.addEventListener(event, handler, false)
  }
}

/**
 * 去除监听
 * @param {Element} element 元素
 * @param {string} event 函数名
 * @param {fn} handler 处理函数
 */
export function off(element, event, handler) {
  if (element && event && handler) {
    element.removeEventListener(event, handler, false)
  }
}

export function getBoundingClientRect(element) {
  if (!element || !element.getBoundingClientRect) {
    return 0
  }
  return element.getBoundingClientRect()
}

/**
 * @description:获取元素偏移量
 */
export function getViewportOffset(element) {
  const doc = document.documentElement

  const docScrollLeft = doc.scrollLeft
  const docScrollTop = doc.scrollTop
  const docClientLeft = doc.clientLeft
  const docClientTop = doc.clientTop

  const pageXOffset = window.pageXOffset
  const pageYOffset = window.pageYOffset

  const box = getBoundingClientRect(element)

  const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box

  const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0)
  const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0)
  const offsetLeft = retLeft + pageXOffset
  const offsetTop = rectTop + pageYOffset

  const left = offsetLeft - scrollLeft
  const top = offsetTop - scrollTop

  const clientWidth = window.document.documentElement.clientWidth
  const clientHeight = window.document.documentElement.clientHeight
  return {
    left: left,
    top: top,
    right: clientWidth - rectWidth - left,
    bottom: clientHeight - rectHeight - top,
    rightIncludeBody: clientWidth - left,
    bottomIncludeBody: clientHeight - top
  }
}

/**
 * object作为url参数转化
 * @param {string} baseUrl url路径
 * @param {object} obj 参数
 * @returns {string}
 */
export function setObjToUrlParams(baseUrl, obj) {
  let parameters = ''
  for (const key in obj) {
    parameters += key + '=' + encodeURIComponent(obj[key]) + '&'
  }
  // 去除结尾&
  parameters = parameters.replace(/&$/, '')
  return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters
}

/**
 * 获取变量类型
 * @param {any} type 变量
 */
export const trueTypeOf = (type) => Object.prototype.toString.call(type).slice(8, -1).toLowerCase()

/**
 * 设置storage
 * @param {string} key 键名
 * @param {json} value 可json化的值
 */
export function setStorage(key = '', value, callback = () => {}) {
  try {
    let json = JSON.stringify(value)
    window.localStorage.setItem(key, json)
    typeof callback === 'function' && callback()
  } catch (error) {
    console.log('localstorage设置失败')
    console.log(error)
  }
}
/**
 * 获取storage
 * @param {string}} key
 */
export function getStorage(key = '') {
  try {
    return JSON.parse(window.localStorage.getItem(key))
  } catch (error) {
    return ''
  }
}

export function clearStorage(key = '') {
  window.localStorage.removeItem(key)
}
